home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / p4 / p4-1_2b.lha / p4-1.2b / lib / p4_sock_util.c < prev    next >
C/C++ Source or Header  |  1993-02-06  |  8KB  |  342 lines

  1. #include "p4.h"
  2. #include "p4_sys.h"
  3. /* p4_net_utils.h generally would suffice here */
  4.  
  5. extern int errno;
  6. extern char *sys_errlist[];
  7.  
  8.  
  9. /*
  10.  *    Utility routines for socket hacking in p4:
  11.  *        P4VOID net_setup_listener(backlog, port, skt)
  12.  *        P4VOID net_setup_anon_listener(backlog, port, skt)
  13.  *        int net_accept(skt)
  14.  *        int net_conn_to_listener(hostname, port)
  15.  *        int net_recv(fd, buf, size)
  16.  *        P4VOID net_send(fd, buf, size)
  17.  *        get_inet_addr(addr)
  18.  *        get_inet_addr_str(str)
  19.  *        dump_sockaddr(who, sa)
  20.  *        dump_sockinfo(msg, fd)
  21.  */
  22.  
  23. /*
  24.  *    Setup a listener:
  25.  *        get a socket
  26.  *        get a port
  27.  *        listen on the port
  28.  *
  29.  *    Note that this does NOT actually start a listener process, but
  30.  *    merely does the listen command.  It might be executed by a
  31.  *    listener process, but we commonly use it prior to actually
  32.  *    forking off the listener.
  33.  */
  34.  
  35.  
  36. P4VOID net_setup_listener(backlog, port, skt)
  37. int backlog;
  38. int port;
  39. int *skt;
  40. {
  41.     struct sockaddr_in sin;
  42.     int rc, optval = TRUE;
  43.  
  44.     SYSCALL_P4(*skt, socket(AF_INET, SOCK_STREAM, 0));
  45.     if (*skt < 0)
  46.     p4_error("net_setup_listener socket", *skt);
  47. #ifdef CAN_DO_SETSOCKOPT
  48.     SYSCALL_P4(rc,setsockopt(*skt, IPPROTO_TCP, TCP_NODELAY, (char *) &optval, sizeof(optval)));
  49. #endif
  50.  
  51.     sin.sin_family = AF_INET;
  52.     sin.sin_addr.s_addr = INADDR_ANY;
  53.     sin.sin_port = htons(port);
  54.  
  55.     SYSCALL_P4(rc, bind(*skt, (struct sockaddr *) & sin, sizeof(sin)));
  56.     if (rc < 0)
  57.     p4_error("net_setup_listener bind", -1);
  58.  
  59.     SYSCALL_P4(rc, listen(*skt, backlog));
  60.     if (rc < 0)
  61.     p4_error("net_setup_listener listen", -1);
  62. }
  63.  
  64. P4VOID net_setup_anon_listener(backlog, port, skt)
  65. int backlog;
  66. int *port;
  67. int *skt;
  68. {
  69.     int rc, sinlen;
  70.     struct sockaddr_in sin;
  71.     int optval = TRUE;
  72.  
  73.     SYSCALL_P4(*skt, socket(AF_INET, SOCK_STREAM, 0));
  74.     if (*skt < 0)
  75.     p4_error("net_setup_anon_listener socket", *skt);
  76. #ifdef CAN_DO_SETSOCKOPT
  77.     SYSCALL_P4(rc, setsockopt(*skt, IPPROTO_TCP, TCP_NODELAY, (char *) &optval, sizeof(optval)));
  78. #endif
  79.  
  80.     sin.sin_family = AF_INET;
  81.     sin.sin_addr.s_addr = INADDR_ANY;
  82.     sin.sin_port = htons(0);
  83.  
  84.     sinlen = sizeof(sin);
  85.  
  86.     SYSCALL_P4(rc, bind(*skt, (struct sockaddr *) & sin, sizeof(sin)));
  87.     if (rc < 0)
  88.     p4_error("net_setup_anon_listener bind", -1);
  89.  
  90.     SYSCALL_P4(rc, listen(*skt, backlog));
  91.     if (rc < 0)
  92.     p4_error("net_setup_anon_listener listen", -1);
  93.  
  94.     getsockname(*skt, (struct sockaddr *) & sin, &sinlen);
  95.     *port = ntohs(sin.sin_port);
  96. }
  97.  
  98. /*
  99.   Accept a connection on socket skt and return fd of new connection.
  100.   */
  101. int net_accept(skt)
  102. int skt;
  103. {
  104.     struct sockaddr_in from;
  105.     int rc, flags, fromlen, skt2, gotit, sockbuffsize;
  106.     int optval = TRUE;
  107.  
  108.     fromlen = sizeof(from);
  109.     gotit = 0;
  110.     while (!gotit)
  111.     {
  112.     p4_dprintfl(60, "net_accept - waiting for accept.\n");
  113.     SYSCALL_P4(skt2, accept(skt, (struct sockaddr *) &from, &fromlen));
  114.     if (skt2 < 0)
  115.         p4_error("net_accept accept", skt2);
  116.     else
  117.         gotit = 1;
  118.     p4_dprintfl(60, "net_accept - got accept\n");
  119.     }
  120. #ifdef CAN_DO_SETSOCKOPT
  121.     SYSCALL_P4(rc, setsockopt(skt2, IPPROTO_TCP, TCP_NODELAY, (char *) &optval, sizeof(optval)));
  122. #endif
  123.     sockbuffsize = SOCK_BUFF_SIZE;
  124.     /******************
  125.       if (setsockopt(skt2,SOL_SOCKET,SO_RCVBUF,(char *)&sockbuffsize,sizeof(sockbuffsize)))
  126.       p4_dprintf("net_accept: setsockopt rcvbuf failed\n");
  127.       if (setsockopt(skt2,SOL_SOCKET,SO_SNDBUF,(char *)&sockbuffsize,sizeof(sockbuffsize)))
  128.       p4_dprintf("net_accept: setsockopt sndbuf failed\n");
  129.       ******************/
  130.  
  131.     flags = fcntl(skt2, F_GETFL, 0);
  132.     if (flags < 0)
  133.     p4_error("net_accept fcntl1", flags);
  134.     flags |= O_NDELAY;
  135.     fcntl(skt2, F_SETFL, flags);
  136.     if (flags < 0)
  137.     p4_error("net_accept fcntl2", flags);
  138.  
  139.     return (skt2);
  140. }
  141.  
  142. int net_conn_to_listener(hostname, port, num_tries)
  143. char *hostname;
  144. int port, num_tries;
  145. {
  146.     int flags, rc, s;
  147.     struct sockaddr_in listener;
  148.     struct hostent *hp;
  149.     P4BOOL optval = TRUE;
  150.     P4BOOL connected = FALSE;
  151.  
  152.     hp = gethostbyname_p4(hostname);
  153.  
  154.     /* p4_dprintfl(70, "net_conn_to_listener: host=%s port=%d\n", hostname, port); */
  155.     p4_dprintfl(80, "net_conn_to_listener: host=%s port=%d\n", hostname, port);
  156.     bzero((P4VOID *) &listener, sizeof(listener));
  157.     bcopy((P4VOID *) hp->h_addr, (P4VOID *) &listener.sin_addr, hp->h_length);
  158.     listener.sin_family = hp->h_addrtype;
  159.     listener.sin_port = htons(port);
  160.  
  161.     connected = FALSE;
  162.     while (!connected && num_tries)
  163.     {
  164.     SYSCALL_P4(s, socket(AF_INET, SOCK_STREAM, 0));
  165.     if (s < 0)
  166.         p4_error("net_conn_to_listener socket", s);
  167.  
  168. #       ifdef CAN_DO_SETSOCKOPT
  169.     SYSCALL_P4(rc, setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *) &optval,sizeof(optval)));
  170. #       endif
  171.  
  172.     SYSCALL_P4(rc, connect(s, (struct sockaddr *) &listener, sizeof(listener)));
  173.     if (rc < 0)
  174.     {
  175.         close(s);
  176.         if (--num_tries)
  177.         {
  178.         p4_dprintfl(00,"net_conn_to_listener: connect to %s failed; will try %d more times \n",hostname,num_tries);
  179.         sleep(1);
  180.         }
  181.     }
  182.     else
  183.     {
  184.         connected = TRUE;
  185.         p4_dprintfl(70,"net_conn_to_listener: connected to %s\n",hostname);
  186.     }
  187.     }
  188.     if (!connected)
  189.     return(-1);
  190.  
  191.     flags = fcntl(s, F_GETFL, 0);
  192.     if (flags < 0)
  193.     p4_error("net_conn_to_listener fcntl1", flags);
  194.     flags |= O_NDELAY;
  195.     fcntl(s, F_SETFL, flags);
  196.     if (flags < 0)
  197.     p4_error("net_conn_to_listener fcntl2", flags);
  198.  
  199.     return (s);
  200. }
  201.  
  202. int net_recv(fd, buf, size)
  203. int fd;
  204. char *buf;
  205. int size;
  206. {
  207.     int recvd = 0;
  208.     int n;
  209.  
  210.     while (recvd < size)
  211.     {
  212.     SYSCALL_P4(n, read(fd, buf + recvd, size - recvd));
  213.     if (n < 0)
  214.     {
  215.         if (errno == EWOULDBLOCK)
  216.         continue;
  217.         else
  218.         p4_error("net_recv read", n);
  219.     }
  220.     recvd += n;
  221.     }
  222.     return (recvd);
  223. }
  224.  
  225. int net_send(fd, buf, size, flag)
  226. int fd;
  227. char *buf;
  228. int size;
  229. int flag;  
  230. /* flag --> fromid < toid; tie-breaker to avoid 2 procs rcving at same time */
  231. /* typically set false for small internal messages, esp. when ids may not */
  232. /*     yet be available */
  233. /* set true for user msgs which may be quite large */
  234. {
  235.     struct p4_msg *dmsg;
  236.     int n, sent = 0;
  237.  
  238.     while (sent < size)
  239.     {
  240.     SYSCALL_P4(n, write(fd, buf + sent, size - sent));
  241.     if (n < 0)
  242.     {
  243.         if (errno == EWOULDBLOCK)
  244.         {
  245.         if (flag)
  246.         {
  247.             if (socket_msgs_available())
  248.             {
  249.             dmsg = socket_recv();
  250.             queue_p4_message(dmsg, p4_local->queued_messages);
  251.             }
  252.         }
  253.         continue;
  254.         }
  255.         else
  256.         {
  257.         p4_error("net_send write", n);
  258.         }
  259.     }
  260.     sent += n;
  261.     }
  262.     return (sent);
  263. }
  264.  
  265. struct hostent *gethostbyname_p4(hostname)
  266. char *hostname;
  267. {
  268.     struct hostent *hp;
  269.     int i = 100;
  270.  
  271.     while ((hp = gethostbyname(hostname)) == NULL)
  272.     {
  273.     if (!--i)
  274.     {
  275.         i = 100;
  276.         p4_dprintfl(00,"gethostbyname failed 100 times for host %s\n",
  277.             hostname);
  278.     }
  279.     }
  280.     return(hp);
  281. }
  282.  
  283. P4VOID get_inet_addr(addr)
  284. struct in_addr *addr;
  285. {
  286.     char hostname[100];
  287.     struct hostent *hp;
  288.  
  289.     hostname[0] = '\0';
  290.     get_qualified_hostname(hostname);
  291.     hp = gethostbyname_p4(hostname);
  292.     bcopy(hp->h_addr, addr, hp->h_length);
  293. }
  294.  
  295. P4VOID get_inet_addr_str(str)
  296. char *str;
  297. {
  298.     struct in_addr addr;
  299.  
  300.     get_inet_addr(&addr);
  301.     strcpy(str, (char *) inet_ntoa(addr));
  302. }
  303.  
  304. #if !defined(CRAY)
  305. /* cray complains about addr being addr of bit field */
  306. /* can probably get around this problem if ever necessary */
  307.  
  308. P4VOID dump_sockaddr(who,sa)
  309. char *who;
  310. struct sockaddr_in *sa;
  311. {
  312.     unsigned char *addr;
  313.  
  314.     addr = (unsigned char *) &(sa->sin_addr.s_addr);
  315.  
  316.     p4_dprintfl(00,"%s: family=%d port=%d addr=%d.%d.%d.%d\n",
  317.         who,
  318.                 ntohs(sa->sin_family),
  319.                 ntohs(sa->sin_port),
  320.                 addr[0], addr[1], addr[2], addr[3]);
  321. }
  322.  
  323. P4VOID dump_sockinfo(msg, fd)
  324. char *msg;
  325. int fd;
  326. {
  327.     int nl;
  328.     struct sockaddr_in peer, me;
  329.  
  330.     p4_dprintfl(00, "Dumping sockinfo for fd=%d: %s\n", fd, msg);
  331.  
  332.     nl = sizeof(peer);
  333.     getpeername(fd, (struct sockaddr *) &peer, &nl);
  334.     dump_sockaddr("Peer",&peer);
  335.        
  336.     nl = sizeof(me);
  337.     getsockname(fd, (struct sockaddr *) &me, &nl);
  338.     dump_sockaddr("Me", &me);
  339. }
  340.  
  341. #endif
  342.